/************************************************************************
 * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
 * @file     wav_dac.c
 * @author   UartTFT Application Team
 * @version  V0.0.1
 * @date     2023-01-01
 * @brief
 *************************************************************************/

#include "wav_dac.h"
#include "transport.h"
#include "pit.h"
#include "data.h"
#include "bsp.h"
#include "pit32_drv.h"
#include "dmac_drv.h"
#include "levetop.h"
#include "dma.h"

/*SPI1 DMA channel base address*/
DMA_CHANNEL_REG *dac_dma_channel[4] = {(DMA_CHANNEL_REG *)(DMA2_BASE_ADDR), (DMA_CHANNEL_REG *)(DMA2_BASE_ADDR + 0x58),
									   (DMA_CHANNEL_REG *)(DMA2_BASE_ADDR + 0xB0), (DMA_CHANNEL_REG *)(DMA2_BASE_ADDR + 0x108)}; // global struct variable for for Channel registers
/*SPI1 DMA config base address */
DMA_CONTROL_REG *dac_dma_control = (DMA_CONTROL_REG *)(DMA2_BASE_ADDR + 0x2C0); // global struct variable for for DMAC registers

#define DAC_TIMER ((PIT32_TypeDef *)PIT2_BASE_ADDR)

uint8_t gWavState = 0;
uint8_t dac_data_buff_1[4096];
uint8_t dac_data_buff_2[4096];
uint32_t gWavFlashAddr = 0;
uint16_t numflag = 0; // Which packet of data is played
uint16_t bufflen = 0;
uint8_t finishflag = 0;
uint8_t wbuf_select = 0;
uint8_t gWavAddrFull_Flag = 0;
uint8_t last_select = 0;
uint8_t gWavType = 0;
uint8_t gWavFlag = 0;
uint16_t buffnum;  // Total number of data packages
uint16_t bufflast; // Data volume of the last packet
uint32_t gWavLen = 0;

uint8_t wav_reduce_para = 0;
uint8_t wav_reduce_para_last = 0;

uint16_t etARRValue(uint16_t sample)
{
	uint16_t arrValue;
	/* Update OCA values to match the. WAV file sampling rate */
	switch (sample)
	{
	case 8000:
		arrValue = (uint16_t)(75000000 / 8000);
		break; /* 8KHz = 75MHz / 9375 */
	case 11025:
		arrValue = (uint16_t)(75000000 / 11025);
		break; /* 11.025KHz = 75MHz / 6802 */
	case 16000:
		arrValue = (uint16_t)(75000000 / 16000);
		break; /* 16KHz = 75MHz / 4687 */
	case 22050:
		arrValue = (uint16_t)(75000000 / 22050);
		break; /* 22.05KHz = 75MHz / 3401 */
	case 44100:
		arrValue = (uint16_t)(75000000 / 44100);
		break; /* 44.1KHz = 75MHz / 1700 */
	case 48000:
		arrValue = (uint16_t)(75000000 / 48000);
		break; /* 48KHz = 75MHz / 1562 */
	default:
		arrValue = 0;
		break;
	}
	return arrValue - 1;
}

void DAC_SetData(uint16_t data)
{
	DAC_Write_Data(data);
	DAC->DAC_SWTR |= SW_TRIG;
	DAC_Wait_Load_Done();
}

static void DAC_Timer_Init(uint32_t rate)
{
	DAC_TIMER->PCSR &= (~PCSR_EN);

	DAC_TIMER->PCSR &= (~PCSR_EN);
	DAC_TIMER->PCSR = (0 << 8) | PCSR_OVW | PCSR_RLD;

	DAC_TIMER->PMR = (g_ips_clk / 1000000 * (1000000 / (float)rate));
	// PIT32->PCSR = (PIT32_CLK_DIV_1<<8)|PCSR_OVW|PCSR_RLD;
}

static void DAC_Timer_Enable(void)
{
	DAC_TIMER->PCSR |= PCSR_EN;
}

static void DAC_Timer_Disable(void)
{
	DAC_TIMER->PCSR &= ~PCSR_EN;
}

void DAC_DMA_Tran(uint8_t channel, uint32_t src, uint32_t length)
{
	// DMA_Init(DMA2_BASE_ADDR);
	dac_dma_control->DMA_CONFIG = 1;
	dac_dma_channel[channel]->DMA_SADDR = src;
	dac_dma_channel[channel]->DMA_DADDR = (uint32_t)&DAC->DAC_DR; // 0x40021004;
	dac_dma_channel[channel]->DMA_CTRL = SIEC | DNOCHG | M2P_DMA | DWIDTH_HW | SWIDTH_HW | INTEN;
	dac_dma_channel[channel]->DMA_CTRL_HIGH = length;

	dac_dma_channel[channel]->DMA_CFG = (HS_SEL_SRC_SOFT) | (HS_SEL_DST_HARD) | (CH_PRIOR3);
	dac_dma_channel[channel]->DMA_CFG_HIGH = DST_PER_DAC;

	dac_dma_control->DMA_MASKTFR |= CHANNEL_UMASK(channel);
	dac_dma_control->DMA_CHEN |= CHANNEL_WRITE_ENABLE(channel) | CHANNEL_ENABLE(channel);
}

void DAC_DMA_dis(uint8_t n)
{
	dac_dma_channel[n]->DMA_CFG |= 1 << 8;
	dac_dma_control->DMA_CHEN |= CHANNEL_WRITE_ENABLE(n);
	dac_dma_control->DMA_CHEN &= ~CHANNEL_ENABLE(n);
	dac_dma_channel[n]->DMA_CFG &= ~(1 << 8);
	dac_dma_control->DMA_CONFIG = ~1;
	dac_dma_control->DMA_CONFIG = 1;
}

void dac_dma_tran(uint8_t *data, uint32_t len)
{
	uint32_t tran_l = 0;
	uint8_t *wDataBufOut = data;
	tran_l = (len >> 1);
	len -= (tran_l << 1);

	// DMA_Init(DMA2_BASE_ADDR);
	DAC_DMA_Tran(WAVdac_CHNUM, (uint32_t)wDataBufOut, tran_l);
}

void close_wav_dac(void)
{
	if (!gWavType)
	{
		var[VAR_WAV * 2] = 0;
		var[VAR_WAV * 2 + 1] = 0;
	}

	gWavFlag = 0;
	gWavAddrFull_Flag = 0;

	WAV_amplifier_DIS();
	DAC_DMA_dis(WAVdac_CHNUM);
	// DAC->DAC_CR &=~DACEN;
	DAC_Timer_Disable();
}

void Wav_DAC_Init(uint16_t num)
{
	uint8_t buff[8];

	close_wav_dac();

	if (num > 0 && num != 0x8000 && (num & 0x7FFF) <= addr_index[5])
	{
		if (num & 0x8000)
			gWavType = 1;
		else
			gWavType = 0;

		LT_ReadFlash_UI(buff, addr_index[4] + ((num & 0x7FFF) - 1) * 8, 8);
		gWavFlashAddr = buff[0] + (buff[1] << 8) + (buff[2] << 16) + (buff[3] << 24);
		gWavLen = buff[4] + (buff[5] << 8) + (buff[6] << 16) + (buff[7] << 24);

		bufflen = 4096;
		if (Flash_Type == 1)
			bufflen = 4096;
		buffnum = gWavLen / bufflen;  // Total number of data packages
		bufflast = gWavLen % bufflen; // Data volume of the last packet
		if (bufflast > 0)
			buffnum++;
		else if (bufflast == 0)
			bufflast = bufflen;

		wbuf_select = 0;
		last_select = 0;
		numflag = 0;
		gWavState = 1;
		gWavFlag = 1;
	}
	else
	{
		gWavType = 0;
		close_wav_dac();
	}
}

void DMA2_IRQHandler(void)
{
	// if (dac_dma_control->DMA_STATTFR & 0x0f) //dma done
	if ((m_dma2_control->DMA_STATTFR & 0x02)) // channel(n) dma done
	{
		finishflag = 1;
		numflag++;
	}

	m_dma2_control->DMA_CLRTFR = m_dma2_control->DMA_STATTFR;
	m_dma2_control->DMA_CLRBLOCK = m_dma2_control->DMA_STATBLOCK;
	m_dma2_control->DMA_CLRSRC = m_dma2_control->DMA_STATSRC;
	m_dma2_control->DMA_CLRDST = m_dma2_control->DMA_STATDST;
	m_dma2_control->DMA_CLRERR = m_dma2_control->DMA_STATERR;

	if (finishflag)
	{
		if (wbuf_select == 0) // Transfer the next packet of data
			dac_dma_tran(dac_data_buff_1, bufflen);
		else if (wbuf_select == 1)
			dac_dma_tran(dac_data_buff_2, bufflen);

		if (numflag == (buffnum - 1)) // Last packet of data
		{
			bufflen = bufflast;
			last_select = 1;
		}
		else if (numflag == buffnum) // Transfer completed
		{
			last_select = 2;
			gWavAddrFull_Flag = 1;
		}
	}
}

uint8_t LT_PlayWav_DAC(void)
{
	uint32_t i = 0;
	short temp = 0;

	if (wav_reduce_para != 0 && wav_reduce_para_last == 0) 
		WAV_amplifier_EN();
	else if (wav_reduce_para == 0 && wav_reduce_para_last != 0)
		WAV_amplifier_DIS();
	wav_reduce_para_last = wav_reduce_para;

	if (gWavState == 1)
	{
		gWavState = 0;
		// Read the first and second packet data
		LT_ReadFlash_UI(dac_data_buff_1, gWavFlashAddr + numflag * bufflen, bufflen);
		for (i = 0; i < bufflen / 2; i++)
		{
			temp = (dac_data_buff_1[2 * i] >> 4) | (dac_data_buff_1[2 * i + 1] << 4);
			temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
			dac_data_buff_1[2 * i] = (temp << 4) & 0xF0;
			dac_data_buff_1[2 * i + 1] = (temp >> 4) & 0xFF;
		}

		numflag++; // numflag=1
		LT_ReadFlash_UI(dac_data_buff_2, gWavFlashAddr + numflag * bufflen, bufflen);
		for (i = 0; i < bufflen / 2; i++)
		{
			temp = (dac_data_buff_2[2 * i] >> 4) | (dac_data_buff_2[2 * i + 1] << 4);
			temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
			dac_data_buff_2[2 * i] = (temp << 4) & 0xF0;
			dac_data_buff_2[2 * i + 1] = (temp >> 4) & 0xFF;
		}

		// Initialize DMA and DAC functions
		DAC_Init(LEFTALIGNED_12BITS, TRIGGER_PIT, DET_ON_RISING);
		// DMA_REG_Init(DMA2_BASE_ADDR);
		dac_dma_control->DMA_CONFIG = 1;

		NVIC_Init(2, 0, DMA2_IRQn, 2);
		DAC_Timer_Init(22050);
		DAC_Timer_Enable();

		if (wav_reduce_para)
			WAV_amplifier_EN();

		dac_dma_tran(dac_data_buff_1, bufflen);
		finishflag = 0;
		wbuf_select = 1;
	}
	if (gWavAddrFull_Flag == 1 && finishflag == 1)
	{
		// printf(" gWavAddrFull_Flag \r\n");
		gWavAddrFull_Flag = 0;
		numflag = 0;
		last_select = 0;
		bufflen = 4096;
		close_wav_dac();
		if (gWavType == 1)
		{
			gWavState = 1;
		}
	}
	if (wbuf_select == 0 && finishflag == 1 && last_select == 0)
	{
		wbuf_select = 1;
		finishflag = 0;
		LT_ReadFlash_UI(dac_data_buff_2, gWavFlashAddr + numflag * bufflen, bufflen);
		for (i = 0; i < bufflen / 2; i++)
		{
			temp = (dac_data_buff_2[2 * i] >> 4) | (dac_data_buff_2[2 * i + 1] << 4);
			temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
			dac_data_buff_2[2 * i] = (temp << 4) & 0xF0;
			dac_data_buff_2[2 * i + 1] = (temp >> 4) & 0xFF;
		}
	}
	else if (wbuf_select == 1 && finishflag == 1 && last_select == 0)
	{
		wbuf_select = 0;
		finishflag = 0;
		LT_ReadFlash_UI(dac_data_buff_1, gWavFlashAddr + numflag * bufflen, bufflen);
		for (i = 0; i < bufflen / 2; i++)
		{
			temp = (dac_data_buff_1[2 * i] >> 4) | (dac_data_buff_1[2 * i + 1] << 4);
			temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
			dac_data_buff_1[2 * i] = (temp << 4) & 0xF0;
			dac_data_buff_1[2 * i + 1] = (temp >> 4) & 0xFF;
		}
	}
	else if (last_select == 1 && finishflag == 1)
	{
		finishflag = 0;
		if (wbuf_select)
		{
			wbuf_select = 0;
			LT_ReadFlash_UI(dac_data_buff_1, gWavFlashAddr + numflag * bufflen, bufflen);
			for (i = 0; i < bufflen / 2; i++)
			{
				temp = (dac_data_buff_1[2 * i] >> 4) | (dac_data_buff_1[2 * i + 1] << 4);
				temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
				dac_data_buff_1[2 * i] = (temp << 4) & 0xF0;
				dac_data_buff_1[2 * i + 1] = (temp >> 4) & 0xFF;
			}
		}
		else
		{
			wbuf_select = 1;
			LT_ReadFlash_UI(dac_data_buff_2, gWavFlashAddr + numflag * bufflen, bufflen);
			for (i = 0; i < bufflen / 2; i++)
			{
				temp = (dac_data_buff_2[2 * i] >> 4) | (dac_data_buff_2[2 * i + 1] << 4);
				temp = (((temp - 2048) * wav_reduce_para) >> 4) + 2048;
				dac_data_buff_2[2 * i] = (temp << 4) & 0xF0;
				dac_data_buff_2[2 * i + 1] = (temp >> 4) & 0xFF;
			}
		}
	}
	return 0;
}
